﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using LitJson;
using OCR.Config;
using OCR.Function;
using OCR.SystemThread;

namespace OCR.SettingsForm
{
    public partial class ProductTemplateConfig_Form : Form
    {
        public static List<List<string>> infosList = new List<List<string>>();
        public static List<List<bool>> insideList = new List<List<bool>>();
        public static List<List<List<Point>>> finalPointlists = new List<List<List<Point>>>();

        public static Bitmap saveBitmap;

        private List<Rectangle> rectangles = new List<Rectangle>();
        private bool isDrawing = false;
        private Point startPoint = Point.Empty;
        Rectangle rect = new Rectangle();
        Rectangle currRect = new Rectangle();

        public static List<List<Point>> pointsList = new List<List<Point>>();

        public static List<List<Point>> finalPointsList = new List<List<Point>>();
        public static List<string> mainInfos = new List<string>();

        public static bool isLocalImg = false;
        public static bool isGetImg = false;

        public static Bitmap cameraRecvBitmap;

        //pictureBox1的初始位置
        private Point PicStartPos;
        //pictureBox1的初始大小
        private Size PicSize;
        //鼠标滚轮缩放图片的增量值
        private int ZoomStep = 20;

        public static string currPath;
        public static DateTime grabImgTime;

        private int rectMaxCount;

        private bool isChangeDrawing = false;

        public static Image rectBitmap;//初始算法识别画框图
        public ProductTemplateConfig_Form()
        {
            InitializeComponent();

            productPB.SizeMode = PictureBoxSizeMode.Zoom;
            
            PicStartPos = productPB.Location;
            PicSize = productPB.Size;

            isGetImg = false;
            isLocalImg = false;

            isChangeDrawing = false;

            productPB.MouseWheel += new MouseEventHandler(productPB_MouseWheel);

            //AlgorithmModule_GPU.CreateInstance();

            //AlgorithmModule_GPU.ImageHandleV2_ByteArray(Application.StartupPath + "\\TemplateInput\\TestFirst.bmp");

        }

        private void ProductTemplateConfig_Form_Load(object sender, EventArgs e)
        {

            ProductTemplateInitial();
        }
        public void ProductTemplateInitial()
        {
            //读取清单
            SetProductConfigListName_Config();
            //获取清单信息
            LocalTemplateList_Config.LocalTemplateSingleInfosInitial(LocalInfo.ProductConfigListName);

            //设置配置清单名称
            productNameTB.Text = LocalTemplateList_Config.LocalTemplateList.ConfigName;

            //设置相机用户集
            productCamCB.SelectedIndex = int.Parse(LocalTemplateList_Config.LocalTemplateList.CameraConfig);

            //设置最大画框数
            rectCountUpDown.Value = LocalTemplateSingleInfos_Config.rectangles.Count;


            //设置配置清单图片以及外框信息
            productPB.Image = Image.FromFile(LocalInfo.Tem_ImgPath);
            productPB.Image = RectPoints((Bitmap)productPB.Image, LocalTemplateSingleInfos_Config.rectangles);
            RectConfigDrawString((Bitmap)productPB.Image, LocalTemplateSingleInfos_Config.rectangles);
            ClearRect_NoPaint();

        }
        /// <summary>
        /// 读取产品配置清单
        /// </summary>
        private void SetProductConfigListName_Config()
        {
            string path = Application.StartupPath + "\\Config\\ProductConfigListName_Config.json";
            ProductConfigListName_Config ProductConfigListName_Config = new ProductConfigListName_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            ProductConfigListName_Config = JsonMapper.ToObject<ProductConfigListName_Config>(re);
            LocalInfo.ProductConfigListName = ProductConfigListName_Config.ProductConfigListName;
            Console.WriteLine("LocalInfo.ProductConfigListName: " + LocalInfo.ProductConfigListName);
            sr.Dispose();
        }

        /// <summary>
        /// 画外框
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="rectangle"></param>
        /// <returns></returns>
        public static Image RectPoints(Bitmap bitmap, Rectangle rectangle)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            graphics1.DrawRectangle(pen, rectangle);

            graphics1.Dispose();
            return convertedImage;
        }
        public static Image RectPoints(Bitmap bitmap, List<Rectangle> rectangles,int scale = 1)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            for (int i = 0; i < rectangles.Count; i++)
            {
                graphics1.DrawRectangle(pen, new Rectangle(rectangles[i].X * scale, rectangles[i].Y * scale, rectangles[i].Width * scale, rectangles[i].Height * scale));
            }


            graphics1.Dispose();
            return convertedImage;
        }

        /// <summary>
        /// 配置清单外框文本--X,Y无需放大2倍 获取的原图大小坐标
        /// </summary>
        /// <param name="img"></param>
        /// <param name="rectangles"></param>
        public void RectConfigDrawString(Bitmap img, List<Rectangle> rectangles)
        {
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X, rectangles[i].Y - 40), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                productPB.Image = result;
                //result.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        /// <summary>
        /// 模板窗口外框文本--X,Y需放大2倍 获取的模板窗口（Size为原图1/2）图片大小坐标
        /// </summary>
        /// <param name="img"></param>
        /// <param name="rectangles"></param>
        public void RectTemplateDrawString(Bitmap img, List<Rectangle> rectangles)
        {
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X * 2, rectangles[i].Y * 2 - 40), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                productPB.Image = result;
                //result.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }

        /// <summary>
        /// 模板识别
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="infos"></param>
        /// <param name="inside"></param>
        public void Compare(Rectangle rect, List<string> infos, List<bool> inside)
        {
            infos.Clear();
            inside.Clear();
            bool isInsideRect = true;
            //Console.WriteLine("识别框个数：" + pointsList.Count);
            //Console.WriteLine("rect.X: " + rect.X.ToString() + "  y: " + rect.Y.ToString());
            //Console.WriteLine("rect.X: " + (rect.X * 2).ToString() + "  y: " + (rect.Y * 2).ToString());
            foreach (var item in pointsList)
            {
                foreach (var x in item)
                {

                    bool x_Inside = rect.X * 2 <= x.X & x.X <= rect.Right * 2;
                    bool y_Inside = rect.Y * 2 <= x.Y & x.Y <= rect.Bottom * 2;
                    //Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                    if (!(x_Inside & y_Inside))
                    {
                        isInsideRect = false;
                        break;
                    }
                    else
                    {
                        isInsideRect = true;
                    }
                }


                inside.Add(isInsideRect);
            }
            //Console.WriteLine("框选信息个数inside：" + inside.Count);

            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    infos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
                else
                {
                    //infos.Add(string.Empty);
                }

            }
            //Console.WriteLine("框选信息个数：" + infos.Count);
            for (int i = 0; i < infos.Count; i++)
            {
                //Console.WriteLine("框选信息内容" + i + "：" + infos[i]);
            }

            for (int i = 0; i < inside.Count; i++)
            {
                //Console.WriteLine("当前画框内" + i + "：" + inside[i]);
            }

            for (int i = 0; i < pointsList.Count; i++)
            {
                //Console.WriteLine("inside_点数组: " + inside[i]);
                if (inside[i])
                {
                    finalPointsList.Add(pointsList[i]);
                    mainInfos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
            }
        }
        /// <summary>
        /// 配置清单模板识别--X,Y无需放大2倍
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="infos"></param>
        /// <param name="inside"></param>
        public void CompareConfig(Rectangle rect, List<string> infos, List<bool> inside)
        {
            infos.Clear();
            inside.Clear();
            bool isInsideRect = true;
            //Console.WriteLine("识别框个数：" + pointsList.Count);
            //Console.WriteLine("rect.X: " + rect.X.ToString() + "  y: " + rect.Y.ToString());
            //Console.WriteLine("rect.X: " + (rect.X * 2).ToString() + "  y: " + (rect.Y * 2).ToString());
            foreach (var item in pointsList)
            {
                foreach (var x in item)
                {

                    bool x_Inside = rect.X <= x.X & x.X <= rect.Right;
                    bool y_Inside = rect.Y <= x.Y & x.Y <= rect.Bottom;
                    //Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                    if (!(x_Inside & y_Inside))
                    {
                        isInsideRect = false;
                        break;
                    }
                    else
                    {
                        isInsideRect = true;
                    }
                }


                inside.Add(isInsideRect);
            }
            //Console.WriteLine("框选信息个数inside：" + inside.Count);

            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    infos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
                else
                {
                    //infos.Add(string.Empty);
                }

            }
            //Console.WriteLine("框选信息个数：" + infos.Count);
            for (int i = 0; i < infos.Count; i++)
            {
                //Console.WriteLine("框选信息内容" + i + "：" + infos[i]);
            }

            for (int i = 0; i < inside.Count; i++)
            {
                //Console.WriteLine("当前画框内" + i + "：" + inside[i]);
            }

            for (int i = 0; i < pointsList.Count; i++)
            {
                //Console.WriteLine("inside_点数组: " + inside[i]);
                if (inside[i])
                {
                    finalPointsList.Add(pointsList[i]);
                    mainInfos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
            }
        }

        /// <summary>
        /// 图片刷新
        /// </summary>
        public void ClearRect()
        {
            rectangles.Clear();
            rect = Rectangle.Empty;
            productPB.Invalidate();

            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);

                    Console.WriteLine("saveBitmap:--" + saveBitmap);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }


            AlgorithmModule_GPU.ImageHandleV2_Opencv(saveBitmap);
            //AlgorithmModule_GPU.ImageHandleV2_ByteArray((Bitmap)saveBitmap.Clone());

            productPB.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            pointsList = AlgorithmModule_GPU.pointsList;

            infosList.Clear();
            insideList.Clear();
            finalPointlists.Clear();


            for (int i = 0; i < rectCountUpDown.Value; i++)
            {
                infosList.Add(new List<string>());
                insideList.Add(new List<bool>());
                finalPointlists.Add(new List<List<Point>>());
            }
        }
        /// <summary>
        /// 图片显示模板信息--不能框选--用于加载配置清单
        /// </summary>
        public void ClearRect_NoPaint()
        {
            rectangles.Clear();
            rect = Rectangle.Empty;
            productPB.Invalidate();

            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);

                    Console.WriteLine("saveBitmap:--" + saveBitmap);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }


            AlgorithmModule_GPU.ImageHandleV2_Opencv(saveBitmap);
            //AlgorithmModule_GPU.ImageHandleV2_ByteArray((Bitmap)saveBitmap.Clone());

            //productPB.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);
            rectBitmap = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            pointsList = AlgorithmModule_GPU.pointsList;

            infosList.Clear();
            insideList.Clear();
            finalPointlists.Clear();


            for (int i = 0; i < LocalTemplateSingleInfos_Config.rectangles.Count; i++)
            {
                infosList.Add(new List<string>());
                insideList.Add(new List<bool>());
                finalPointlists.Add(new List<List<Point>>());
            }

            productPB.Image = TemplateCompare((Bitmap)productPB.Image);
        }

        public void ClearLastRect()
        {
            if (rectangles.Count == 0)
                return;
            rectangles.Remove(rectangles[rectangles.Count - 1]);

            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);

                    Console.WriteLine("saveBitmap:--" + saveBitmap);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }

            //AlgorithmModule_GPU.ImageHandleV2_Opencv(saveBitmap);
            //MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            productPB.Image = RectPoints((Bitmap)rectBitmap, rectangles,2);

            RectTemplateDrawString((Bitmap)productPB.Image, rectangles);

            rect = Rectangle.Empty;
            productPB.Invalidate();
        }

        /// <summary>
        /// 打开图片文件夹
        /// </summary>
        /// <returns></returns>
        public string OpenImageWithDialog()
        {
            string path;
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        Console.WriteLine("openFileDialog.FileName: " + openFileDialog.FileName);
                        //return new Bitmap(openFileDialog.FileName);
                        openFileDialog.Dispose();
                        return openFileDialog.FileName;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"无法打开文件: {ex.Message}");
                        return null;
                    }
                }

            }
            return null;
        }

        /// <summary>
        /// 统一模板---->判断模板数组中的模板是否完全相同
        /// </summary>
        /// <param name="arrays"></param>
        /// <returns></returns>
        bool AreArraysContentEqual(List<List<string>> arrays)
        {
            if (AreAllArraysEmpty(arrays)) return false;

            if (arrays.Count == 0) return false;

            if (arrays.Count == 1) return true;

            // 基准数组频率统计
            var baseFreq = arrays[0]
                .GroupBy(s => s)
                .ToDictionary(g => g.Key, g => g.Count());

            for (int i = 1; i < arrays.Count; i++)
            {
                // 当前数组频率统计
                var currFreq = arrays[i]
                    .GroupBy(s => s)
                    .ToDictionary(g => g.Key, g => g.Count());

                // 比较频率字典
                if (!baseFreq.Count.Equals(currFreq.Count) ||
                    baseFreq.Any(kv => !currFreq.TryGetValue(kv.Key, out int count) || count != kv.Value))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// 判断模板数组中的模板是否为空字符串
        /// </summary>
        /// <param name="arrays"></param>
        /// <returns></returns>
        bool AreAllArraysEmpty(List<List<string>> arrays)
        {
            return arrays.All(arr =>
                arr != null &&
                arr.All(string.IsNullOrEmpty));
        }
        /// <summary>
        /// 配置清单识别
        /// </summary>
        /// <param name="rectBitmap"></param>
        /// <returns></returns>
        public Image TemplateCompare(Bitmap rectBitmap)
        {
            finalPointsList.Clear();
            mainInfos.Clear();

            for (int i = 0; i < LocalTemplateSingleInfos_Config.rectangles.Count; i++)
            {
                CompareConfig(LocalTemplateSingleInfos_Config.rectangles[i], infosList[i], insideList[i]);
            }
            Console.WriteLine("finalPointsList.Count:" + finalPointsList.Count);
            Console.WriteLine("mainInfos.Count:" + mainInfos.Count);
            Image bitmap = AlgorithmModule_GPU.RectPoints1(rectBitmap, finalPointsList, mainInfos);
            return bitmap;
        }

         
        private void SetTem_RectMaxCount_Config()
        {
            string path = Application.StartupPath + "\\Config\\Tem_RectMaxCount_Config.json";
            Tem_RectMaxCount_Config tem_RectMaxCount_Config = new Tem_RectMaxCount_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            tem_RectMaxCount_Config = JsonMapper.ToObject<Tem_RectMaxCount_Config>(re);
            LocalInfo.Tem_RectMaxCount = int.Parse(tem_RectMaxCount_Config.Tem_RectMaxCount);
            Console.WriteLine("LocalInfo.Tem_RectMaxCount: " + LocalInfo.Tem_RectMaxCount);
            sr.Dispose();
        }

        /// <summary>
        /// 打开配置清单文件夹
        /// </summary>
        /// <returns></returns>
        public string OpenJsonWithDialog()
        {
            string path= "\\LocalTemplateListConfigs";
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = Application.StartupPath + path;
                openFileDialog.Filter = "配置文件|*.json";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        Console.WriteLine("openFileDialog.SafeFileName: " + openFileDialog.SafeFileName);
                        openFileDialog.Dispose();
                        return openFileDialog.SafeFileName;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"无法打开文件: {ex.Message}");
                        return null;
                    }
                }

            }
            return null;
        }


        private void productPB_MouseWheel(object sender, MouseEventArgs e)
        {
            if (productPB.Image == null) return;
            Console.WriteLine("ZoomStep--------------" + ZoomStep);
            PictureBox pbox = productPB;
            int x = e.Location.X;
            int y = e.Location.Y;
            int ow = pbox.Width;
            int oh = pbox.Height;
            int VX, VY;  //因缩放产生的位移矢量

            int ow1 = rect.Width;
            int oh1 = rect.Height;
            int VX1, VY1;  //因缩放产生的位移矢量
            if (e.Delta > 0)
            {
                if (pbox.Width >= 1624)
                    return;

                pbox.Width = 2 * pbox.Width;
                pbox.Height = 2 * pbox.Height;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //第3步
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;

                //this.rect.Width = pbox.Width/2;
                //this.rect.Height = pbox.Height/2;
            }
            if (e.Delta < 0)
            {
                //防止一直缩成负值
                if (pbox.Width <= 812)
                    return;

                pbox.Width = pbox.Width / 2;
                pbox.Height = pbox.Height / 2;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                 BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;
            }
            if (e.Delta > 0) //放大
            {
                ////第1步
                //pbox.Width += ZoomStep;
                //pbox.Height += ZoomStep;
                ////第2步
                //PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                //Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                ////第3步
                //pbox.Width = rect.Width;
                //pbox.Height = rect.Height;

                //this.rect.Width -= ZoomStep;
                //this.rect.Height -= ZoomStep;



                //Console.WriteLine(string.Format("宽：{0}，高：{1}",pbox.Width,pbox.Height));
            }
            if (e.Delta < 0) //缩小
            {
                ////防止一直缩成负值
                //if (pbox.Width < 300)
                //    return;

                //pbox.Width -= ZoomStep;
                //pbox.Height -= ZoomStep;
                //PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                // BindingFlags.NonPublic);
                //Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //pbox.Width = rect.Width;
                //pbox.Height = rect.Height;
            }

            //第4步，求因缩放产生的位移，进行补偿，实现锚点缩放的效果
            VX = (int)((double)x * (ow - pbox.Width) / ow);
            VY = (int)((double)y * (oh - pbox.Height) / oh);
            pbox.Location = new Point(pbox.Location.X + VX, pbox.Location.Y + VY);



            Console.WriteLine("pbox.Width:===" + pbox.Width);

            if (pbox.Width == 812)
            {
                //设置坐标
                productPB.Location = PicStartPos;
                //设置控件宽高
                productPB.Size = PicSize;
            }
        }

        private void productPB_MouseDown(object sender, MouseEventArgs e)
        {

            if (e.Button == MouseButtons.Left)
            {
                if (rectangles.Count >= rectCountUpDown.Value)
                {
                    MessageBox.Show("已到画框上限");
                }

                isDrawing = true;
                rect = Rectangle.Empty;
                startPoint = e.Location;
                productPB.Invalidate();

            }
            if (e.Button == MouseButtons.Right)
            {
                //ClearRect();
                ClearLastRect();
            }
        }

        private void productPB_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (!isChangeDrawing)
                    return;
                if (isDrawing)
                {
                    int x = e.X > startPoint.X ? startPoint.X : e.X;
                    int y = e.Y > startPoint.Y ? startPoint.Y : e.Y;
                    int width = Math.Abs(e.X - startPoint.X);
                    int height = Math.Abs(e.Y - startPoint.Y);


                    rect = new Rectangle(x, y, width, height);
                    currRect = new Rectangle(x * 2, y * 2, width * 2, height * 2);
                    productPB.Invalidate();

                }
            }
        }

        private void productPB_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDrawing = false;

                if (productPB.Width == 1624)
                {
                    rect = new Rectangle(rect.X / 2, rect.Y / 2, rect.Width / 2, rect.Height / 2);
                }
                else if (productPB.Width == 406)
                {
                    rect = new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2);
                }

                Console.WriteLine("rect.X: " + rect.X + " rect.Y: " + rect.Y + " rect.Width: " + rect.Width + " rect.Height: " + rect.Height);
                Console.WriteLine("rect.Location: " + rect.Location + " rect.Right: " + rect.Right + " rect.Left: " + rect.Left + " rect.Top: " + rect.Top + " rect.Bottom: " + rect.Bottom);
                Console.WriteLine("rect.X: " + rect.X * 2 + " rect.Y: " + rect.Y * 2 + " rect.Width: " + rect.Width * 2 + " rect.Height: " + rect.Height * 2);
                //rect = new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2);

                productPB.Image = RectPoints((Bitmap)productPB.Image, new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2));


                if (rect.X == 0)
                    return;

                rectangles.Add(rect);

                Console.WriteLine("up_rectangles.Count: " + rectangles.Count);

                RectTemplateDrawString((Bitmap)productPB.Image, rectangles);

                rect = Rectangle.Empty;
                productPB.Invalidate();
            }
        }

        private void productPB_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Color.Red, 4), rect);
        }

        private void LoadConfigBtn_Click(object sender, EventArgs e)
        {
            string configListPath = OpenJsonWithDialog();

            if (configListPath == null)
                return;

            //获取清单信息
            LocalTemplateList_Config.LocalTemplateSingleInfosInitial(configListPath);

            //设置配置清单名称
            productNameTB.Text = LocalTemplateList_Config.LocalTemplateList.ConfigName;

            //设置相机用户集
            productCamCB.SelectedIndex = int.Parse(LocalTemplateList_Config.LocalTemplateList.CameraConfig);

            //设置最大画框数
            rectCountUpDown.Value = LocalTemplateSingleInfos_Config.rectangles.Count;


            //设置配置清单图片以及外框信息
            productPB.Image = Image.FromFile(LocalInfo.Tem_ImgPath);
            productPB.Image = RectPoints((Bitmap)productPB.Image, LocalTemplateSingleInfos_Config.rectangles);
            RectConfigDrawString((Bitmap)productPB.Image, LocalTemplateSingleInfos_Config.rectangles);
            ClearRect_NoPaint();

            LocalInfo.ProductConfigListName = configListPath;
            LocalInfo.ProductConfigListName_Config_InfoUpdate();
        }

        private void ChangeConfigBtn_Click(object sender, EventArgs e)
        {
            LoadConfigBtn.Enabled = false;

            productNameTB.Enabled = true;
            productCamCB.Enabled = true;
            TemplateGB.Enabled = true;
            SaveConfigBtn.Enabled = true;
            cancelChangeBtn.Enabled = true;

            //productPB.Image = Image.FromFile(LocalInfo.Tem_ImgPath);

            productPB.Image = AlgorithmModule_GPU.RectPoints1((Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath), AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            string dateTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff");
            productNameTB.Text = dateTime;

            isChangeDrawing = true;
        }

        private void rectCountUpDown_ValueChanged(object sender, EventArgs e)
        {
            rectMaxCount = (int)rectCountUpDown.Value;
        }

        private void rectCountChangeBtn_Click(object sender, EventArgs e)
        {
            rectCountUpDown.Enabled = true;

            rectCountChangeBtn.Enabled = false;
            rectCountConfirmBtn.Enabled = true;
        }

        private void rectCountConfirmBtn_Click(object sender, EventArgs e)
        {
            try
            {
                //LocalInfo.Tem_RectMaxCount_Config_InfoUpdate();
                rectCountUpDown.Enabled = false;
                rectCountChangeBtn.Enabled = true;
                rectCountConfirmBtn.Enabled = false;
                MessageBox.Show("修改成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            ClearRect();
        }

        private void GetCameraImgBtn_Click(object sender, EventArgs e)
        {
            isLocalImg = false;
            isGetImg = true;

            if (!CameraReceiveThread.isGrabbing)
            {
                CameraReceiveThread.CameraInitialize();
            }

            if (!CameraReceiveThread.isGrabbing)
                return;

            CameraTriggerThread_MultiTemplateList.iCameraTrigger_Step = 3;
        }

        private void GetLocalImgBtn_Click(object sender, EventArgs e)
        {
            string path = OpenImageWithDialog();

            if (path == null)
                return;
            currPath = path;

            isLocalImg = true;
            isGetImg = true;

            ClearRect();
        }

        private void TemplateCompareBtn_Click(object sender, EventArgs e)
        {
            Console.WriteLine("rectangles.Count:" + rectangles.Count);
            if (rectangles.Count != rectCountUpDown.Value)
            {
                MessageBox.Show("未到画框个数！");
                return;
            }
            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }

            finalPointsList.Clear();
            mainInfos.Clear();
            for (int i = 0; i < rectangles.Count; i++)
            {
                Compare(rectangles[i], infosList[i], insideList[i]);
            }


            bool isMultiTemSame = AreArraysContentEqual(infosList);
            Console.WriteLine("isMultiTemSame: " + isMultiTemSame);
            if (UnifiedTemCB.Checked)
            {
                if (!isMultiTemSame)
                {
                    MessageBox.Show("多个模板需相同");
                    return;
                }

            }

            Image bitmap = AlgorithmModule_GPU.RectPoints1(saveBitmap, finalPointsList, mainInfos);
            RectTemplateDrawString((Bitmap)bitmap,rectangles);

            List<Rectangle> finalRectangles = new List<Rectangle>();
            foreach (var item in rectangles)
            {
                finalRectangles.Add(new Rectangle(item.X * 2, item.Y * 2, item.Width * 2, item.Height * 2));
            }


            productPB.Image = AlgorithmModule_GPU.RectPoints((Bitmap)productPB.Image, finalRectangles);
            //RectDrawString((Bitmap)MultiTemplatePb.Image);
            Console.WriteLine("finalPointsList.Count:" + finalPointsList.Count);
            Console.WriteLine("infosList.mainInfos:" + mainInfos.Count);

            for (int i = 0; i < infosList.Count; i++)
            {
                Console.WriteLine("infosList[i].Count:" + infosList[i].Count);
            }

            MessageBox.Show("识别完成！");
        }

        private void SaveConfigBtn_Click(object sender, EventArgs e)
        {
            using(SaveFileDialog saveDialog = new SaveFileDialog())
            {
                // 配置保存对话框
                saveDialog.Title = "保存图片";
                saveDialog.Filter = "BMP 图片|*.bmp|JPEG 图片|*.jpg|PNG 图片|*.png|所有文件|*.*";
                saveDialog.DefaultExt = "jpg";
                saveDialog.AddExtension = true;

                string dateTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff");
                saveDialog.FileName = dateTime;

                // 显示对话框并处理结果
                if (saveDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        // 根据扩展名选择保存格式
                        string extension = Path.GetExtension(saveDialog.FileName).ToLower();
                        ImageFormat format = ImageFormat.Jpeg; // 默认格式

                        switch (extension)
                        {
                            case ".png":
                                format = ImageFormat.Png;
                                break;
                            case ".bmp":
                                format = ImageFormat.Bmp;
                                break;
                                // JPEG和其他格式使用默认处理
                        }
                        Console.WriteLine(saveDialog.FileName);
                        string targetPath = saveDialog.FileName;

                        using (saveBitmap)
                        {
                            using (var newBitmap = new Bitmap(saveBitmap.Width, saveBitmap.Height))
                            {
                                using (var graphics = Graphics.FromImage(newBitmap))
                                {
                                    graphics.DrawImage(saveBitmap, 0, 0);
                                    saveBitmap.Dispose();
                                    Bitmap finalBitmap = AlgorithmModule_GPU.ConvertTo8bpp(newBitmap);
                                    // 保存图片
                                    finalBitmap.Save(targetPath, format);
                                    //saveBitmap.Save(targetPath);
                                    LocalInfo.Tem_ImgPath = targetPath;
                                    LocalInfo.Tem_ImgPath_Config_InfoUpdate();
                                    MessageBox.Show("图片保存成功！");
                                    graphics.Dispose();
                                    saveBitmap = (Bitmap)Image.FromFile(targetPath);
                                }


                            }
                        }

                        List<LocalTemplateSingleInfo> localTemplateSingleInfos = new List<LocalTemplateSingleInfo>();
                        for (int i = 0; i < infosList.Count; i++)
                        {
                            Console.WriteLine("infosList[i].Count:" + infosList[i].Count);

                            //if (infosList[i].Count > 0) { }

                            LocalTemplateSingleInfo localTemplateSingleInfo = new LocalTemplateSingleInfo();
                            localTemplateSingleInfo.InfoList = infosList[i];
                            localTemplateSingleInfo.rect_X = rectangles[i].X.ToString();
                            localTemplateSingleInfo.rect_Y = rectangles[i].Y.ToString();
                            localTemplateSingleInfo.rect_Width = rectangles[i].Width.ToString();
                            localTemplateSingleInfo.rect_Height = rectangles[i].Height.ToString();
                            localTemplateSingleInfos.Add(localTemplateSingleInfo);
                        }
                        Console.WriteLine("localTemplateSingleInfos.Count:" + localTemplateSingleInfos.Count);

                        LocalTemplateSingleInfos_Config.LocalTemplateInfoSave(localTemplateSingleInfos);

                        LocalTemplateSingleInfos_Config.LocalTemplateSingleInfosInitial();
                        OCR_Form.SetLocalTemplateInfos();

                        OCR_Form.oCR_Form.LocalTemplateInfoLabel.Text = "模板1";
                        OCR_Form.currLocalTemplateInfoIndex = 0;
                        OCR_Form.SetLocalTemplateInfos(OCR_Form.currLocalTemplateInfoIndex);

                        LocalTemplateList localTemplateList = new LocalTemplateList();
                        localTemplateList.ConfigID = Guid.NewGuid().ToString("N");
                        localTemplateList.ConfigName = productNameTB.Text;
                        localTemplateList.LocalTemplateSingleInfos = localTemplateSingleInfos;
                        localTemplateList.TemplateImgPath = targetPath;
                        localTemplateList.CameraConfig = productCamCB.SelectedIndex.ToString();

                        LocalTemplateList_Config.LocalTemplateInfoSave(localTemplateList);
                        MessageBox.Show("配置保存成功！");

                        LocalInfo.ProductConfigListName = localTemplateList.ConfigName + "_LTL" + ".json";
                        LocalInfo.ProductConfigListName_Config_InfoUpdate();

                        ProductTemplateInitial();

                        LoadConfigBtn.Enabled = true;

                        productNameTB.Enabled = false;
                        productCamCB.Enabled = false;
                        TemplateGB.Enabled = false;
                        SaveConfigBtn.Enabled = false;
                        cancelChangeBtn.Enabled = false;

                        isGetImg = false;
                        isLocalImg = false;

                        isChangeDrawing = false;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"保存失败：{ex.Message}");
                    }
                }
            }
        }

        private void ProductTemplateConfig_Form_FormClosed(object sender, FormClosedEventArgs e)
        {
            rectBitmap.Dispose();
            saveBitmap.Dispose();
            OCR_Form.ProductTemplateConfig_Form = null;
        }

        private void cancelChangeBtn_Click(object sender, EventArgs e)
        {
            ProductTemplateInitial();

            LoadConfigBtn.Enabled = true;

            productNameTB.Enabled = false;
            productCamCB.Enabled = false;
            TemplateGB.Enabled = false;
            SaveConfigBtn.Enabled = false;
            cancelChangeBtn.Enabled = false;

            isGetImg = false;
            isLocalImg = false;

            isChangeDrawing = false;
        }

        private void ProductTemplateConfig_Form_KeyDown(object sender, KeyEventArgs e)
        {
            if (!isChangeDrawing)
                return;
            if (e.KeyCode == Keys.D0)
            {
                ClearRect();
            }
        }
    }
}
